<?php
if (! defined ( 'IN_BIC' )) {
    die ( '非法路由访问来源!' );
}
class Bic_Router extends Bic_Base{

    /**
     * 路由类型,分2类：
     * 	1|normal	:普通型。
     * 		不用开启重写。但会带个问号"?",入口文件，默认为index.php（以服务器设定为准）。
     * 		url原型如：
     * 		http://example.com/？controller=$controller&action=$action
     * 	2|rewrite	:重写型。
     * 		必须开启重写的支持。
     * 		url原型如：
     * 		http://example.com/controller/action/key/value/key/value
     * @var string
     */
    private static $_type = 'normal';

    public static $_routes = array();
    
    /**
     * 当前路由
     * @var array
     */
    public static $_currentRoute = null;
    
    /**
     *路由匹配规则类型
     * @var type 
     * 1|custom：自定义类型 
     * 2|system：系统类型
     */
    public static $_rulerMatchType = 'custom';
    
    private static $_currentController = null;
    
    private static $_currentAction = null;
    
    private static $_matchRoute = null;
    
    /**
     * URL中的参数队列
     * @var array
     */
    private static $_params =  array();
    
    /**
     * 是否已经添加过默认路由
     * @var bool
     */
    private static $_addDefaultRoutesed = false;
    /**
     *默认路由变量匹配规则
     * @var type 
     */
    private static $_defaultRouteParamReg = '[a-zA-Z_0-9][a-zA-Z0-9_]*';
    /**
     *变量起始符号
     * 如/list/:action.html 中的:action就是变量
     * @var type 
     */
    private static $_urlVariableDelimiter = ':';
    
    /**
     * 默认控制器
     * @var string
     */
    public static $_defaultController = 'Index';
    public static $_defaultAction = 'display';
    
    public static $_url = null;
    /**
     *url参数分割符
     * @var type 
     */
    private static $_urlDelimiter = '/';
    
    public static $_prefix = null;
    public static $_suffix = '.html';
    
    public static $_debug = false;
    

    public function __construct($route,$default=array(),$option=array()){
        self::addRoute($route,$default,$option);
    }

    /**
     *添加自定义路由
     * @param type $route
     * @param type $default
     * @param type $option
     * @return type 
     */
    public static function addRoute($route,$default=array(),$option=array()){
        self::$_routes[] = array(
            'route' => $route,
            'default' => $default,
            'option'   => $option
        );
        return self::$_routes;
    }
    
    /**
     * 获取已注册的所有路由
     */
    public static function getRoutes(){
        return self::$_routes;
    }
    
    /**
     *获取当前路由匹配规则类型
     * @return type 
     */
    public static function getRulerMatchType(){
        return self::$_rulerMatchType;
    }
    
    /**
     *设置路由匹配规则类型
     * @param type $type 
     */
    public static function setRulerMatchType($type){
        if ($type != 'system' && $type != 'custom')
            throw new Bic_Exception ('路由匹配规则类型只能是system(系统)或custom(自定义)');
        
        self::$_rulerMatchType = $type;
    }
    
    /**
     * 返回当前匹配的路由
     * @param string $uri	HTTP uri 信息
     */
    public static function getCurrentRoute($uri=null){
        if (!$uri){
            $http = new Bic_Controller_Request_Http();
            $uri = $http->getRequestUri();
        }
        
        //添加默认路由
        self::addDefaultRoutes();
        
        /**
         * 匹配路由器-1
         *      使用系统路由匹配
         */
        if (self::$_rulerMatchType == 'system' || ('' != $_GET['controller'] && '' != $_GET['action'])){
            $routes_val = null;
            if ($_GET['controller'] == ''){
                $_GET['controller'] = self::$_defaultController;
            }
            if ($_GET['action'] == ''){
                $_GET['action'] = self::$_defaultAction;
            }
            
            $routes_val['default']['controller'] = $_GET['controller'];
            $routes_val['default']['action'] = $_GET['action'];
            
            self::$_currentController = $routes_val['default']['controller'];
            self::$_currentAction = $routes_val['default']['action'];
        
            self::$_currentRoute = $routes_val;
            
            if(self::$_debug){
                So(self::$_currentRoute);
                So(self::$_params);
            }
            
            return $routes_val;
        }
        
        /**
         * 匹配路由器-2
         * 	返回匹配的路由器的索引
         * @var string
         */
        $route_index = self::match($uri);
        
        /**
         *使用默认路由进行设置 
         */
        if(is_null($route_index)){
            
        }
        
        if(self::$_debug){
            So("当前uri：{$uri}");
            So('当前已匹配的路由:');
            So(self::$_currentRoute);
            So('当前路由参数:');
            So(self::$_params);
            So('所有添加的路由:');
            So(self::$_routes);
        }
        
        //返回当前匹配的路由器
        return self::$_routes[$route_index];
    }

    /**
     * 匹配自定义路由
     * @param string $uri
     */
    private static function match($uri){
        if (strpos($uri,'?') !== false){
            $uris = explode('?',$uri);
            if (count($uris) == 2 && $uris[0] != '/'){
                $uri = $uris[0];
            }else{
                $uri = $uris[1];
            }
        }else if('normal' == self::$_type){
            $uri= $uri;
        }
        
        $uri = '/'.ltrim(str_replace(self::$_suffix,'',trim($uri,self::$_urlDelimiter)),'/');
        
        $routes = array_reverse(self::getRoutes());    //$route,self::$_urlDelimiter

        foreach ($routes as $routes_key => $routes_val){
            //获取用于url匹配正则参数
            $pattern = self::getRegPattern($routes_val);
            if(preg_match("/^{$pattern['pattern']}$/sm",urldecode($uri),$result)){
                unset($_GET['url']);
                /**
                 *获取参数 
                 * 当匹配值超过1个的时候，才会出现参数
                 */
                //匹配通配符
                if (strpos($pattern['pattern'],'.*') !== false){
                    $all_pattern_value = array_pop($result);
                    $all_pattern_value = explode(self::$_urlDelimiter, trim($all_pattern_value,self::$_urlDelimiter));
                    //这里要把完全匹配的参数提取出来
                    while (count($all_pattern_value)>1){
                        $params[array_shift($all_pattern_value)] = array_shift($all_pattern_value);
                    }
                }
                //匹配正常参数
                if (count($result)>1){
                    for($i=1;$i<count($result);$i++){
                        $params[$pattern['paramKeys'][$i-1]] = $result[$i];
                    }
                    //默认值
                    $params = array_merge($routes_val['default'], array_filter($params));
                }
                //生成参数
                if (!empty($params)){
                    self::$_params = $params;
                }
                //$uri_arr = explode(self::$_urlDelimiter,$uri);
                if(empty($routes_val['default']['controller'])){
                    $routes_val['default']['controller'] = empty(self::$_params['controller']) ? (self::$_defaultController) : (self::$_params['controller']);
                }
                if(empty($routes_val['default']['action'])){
                    $routes_val['default']['action'] = empty(self::$_params['action']) ? self::$_defaultAction : self::$_params['action'];
                }
                
                //controller与action不要注册到路由变量中
                unset(self::$_params['controller'],self::$_params['action']);
                
                /**
                 * 设置当前路由
                 */
                self::$_currentRoute = $routes_val;
                
                self::$_currentController = $routes_val['default']['controller'];
                self::$_currentAction = $routes_val['default']['action'];
                
                /**
                 * 返回当前路由索引
                 */
                return $routes_key;
            }
            
            self::$_params = array();
        }
    }
    
    /**
     *生成Reg规则
     * @param type $route
     * @return string 
     */
    protected static function getRegPattern($route){
        $route['pattern']   = $route['route'];
        $route['paramKeys']     = array();
        //匹配星号*模式
        if (strpos($route['pattern'], '*') !== false ){
            $route['pattern'] = str_replace('*', '(.*)', $route['pattern']);
        }
        if (strpos($route['pattern'], ':') !== false ){
            /**
             * 这里的变量采用php变量相同的规则，
             * 匹配的是一个合法的php变量
             */
            preg_match_all('/:([a-zA-Z_0-9][a-zA-Z0-9_]*)/', $route['pattern'], $declareParams);
            //变量
            $route['paramKeys'] = $declareParams[1];
            //变量匹配正则规则
            foreach ($declareParams[1] as $val){
                if (empty($route['option'][$val])){
                    //未定义规则的变量
                    //将她们都设置为默认变量规则
                    $route['pattern'] = str_replace(":{$val}", '('.self::$_defaultRouteParamReg.')', $route['pattern']);
                }else{
                    //设置自定义规则
                    $route['pattern'] = str_replace(":{$val}",'('.trim(trim($route['option'][$val],')'),'(').')',$route['pattern']);
                }
            }
        }
        $route['pattern'] = '\/'.str_replace('/','\/',$route['pattern']);
        $route['option'] = array_keys($route['option']);
        return $route;
        
        /* 这里应该是要删掉的，先保留，上面的功能做完后，就删除
        self::$_params[] = $regs[1];
        
        if(!empty(self::$_matchRoute[2][$regs[1]])){
            return $reg = '('.rtrim(ltrim(self::$_matchRoute[2][$regs[1]],'('),')').')';
        }
        return '(\w+)';
         * 
         */
    }
    
    /**
     * 默认路由
     */
    public static function addDefaultRoutes(){
        if(!self::$_addDefaultRoutesed){
            //添加默认路由
            //这里添加到最开头的位置，因为后面要反转,
            //使默认路由最后才进行匹配
            array_unshift(self::$_routes,array(":controller/*"));
            array_unshift(self::$_routes,array(":controller/:action/*"));
            self::$_addDefaultRoutesed = true;
        }
    }
    
    /**
     * 当前控制器
     * @return string
     */
    public static function getCurrentController(){
        if (self::$_currentController){
            return self::$_currentController;
        }else{
            throw new Bic_Exception('Route error:Loading Controller fault!');
        }
    }
    
    /**
     * 当前动作
     * @return unknown_type
     */
    public static function getCurrentAction(){
        if (self::$_currentAction){
            return self::$_currentAction;
        }else{
            throw new Bic_Exception('Route error:Loading Action fault!');
        }
    }
    
    public static function getParams(){
        return self::$_params;
    }
    
    public function writeUrl(){}

    public function getType(){
        return self::$_type;
    }
    
    public static function setType($t){
        if($t=='normal' || $t=='rewrite'){
            self::$_type=$t;
        }else{
            throw new Bic_Exception('路由类型设置出错！');
        }
    }
    
    /**
     *设置默认路由
     * @param type $controller 
     */
    public static function setDefaultController($controller){
        self::$_defaultController = $controller;
    }
    
    /**
     *设置默认控制器
     * @param type $action 
     */
    public static function setDefaultAction($action){
        self::$_defaultAction = $action;
    }


    /**
     * 设置url后缀
     * @param string $suffix
     */
    public static function setSuffix($suffix=null) {
        $suffix = trim($suffix,'.');
        if($suffix ){
                return self::$_suffix='.'.$suffix;
        }
    }
    /**
     *获取默认变量规则
     * @return type 
     */
    public static function getDefaultRouteParamReg(){
        return self::$_defaultRouteParamReg;
    }
    /**
     *设置默认变量规则
     * @param type $defaultRouteParamReg
     * @return boolean 
     */
    public static function setDefaultRouteParamReg($defaultRouteParamReg){
        if (!$defaultRouteParamReg)
            return false;
        return self::$_defaultRouteParamReg = $defaultRouteParamReg;
    }
    /**
     *获取URL变量起始符
     * @return type 
     */
    public static function getUrlVariableDelimiter(){
        return self::$_urlVariableDelimiter;
    }
    /**
     *设置URL变量起始符
     * @param type $urlVariableDelimiter
     * @return boolean 
     */
    public static function setUrlVariableDelimiter($urlVariableDelimiter){
        if (!$urlVariableDelimiter)
            return false;
        return self::$_urlVariableDelimiter = $urlVariableDelimiter;
    }
    /**
     *获取URL参数分割符
     * @return type 
     */
    public static function getUrlDelimiter(){
        return self::$_urlDelimiter;
    }
    /**
     *设置URL参数分割符
     * @param type $urlVariableDelimiter
     * @return boolean 
     */
    public static function setUrlDelimiter($urlDelimiter){
        if (!$urlDelimiter)
            return false;
        return self::$_urlDelimiter = $urlDelimiter;
    }
}
